home *** CD-ROM | disk | FTP | other *** search
- # jedit_util.tcl - utility procedures for jedit, a tk-based editor
- #
- # Copyright 1992-1994 by Jay Sekora. All rights reserved, except
- # that this file may be freely redistributed in whole or in part
- # for non-profit, noncommercial use.
-
- # TO DO
- # abbrev fixes:
- # maybe some heuristics for things like plurals
- # maybe a syntax for suffixes (e.g., commit;t -> commitment)
- # file_modes panel
- # documentation for keybindings (automatic documentation?)
- # problem with filename getting set when you cancel Save
- # for the first time on a new unnamed file
- # improve find panel
- # have find wrap around (if last time didn't match)
- # regex search/replace
- # find all at once (mark) and cycle through with tag nextrange
- # gesture commands
- # autobreaking space a problem if you use two spaces betw sentences
- # word-end punctuation (and heuristics) sd be mode-specific
-
- # CHANGES:
- # house(s) the s won't expand
- # return key checkpoints!
- # improved mode handling (hooks)
-
- ######################################################################
-
- ######################################################################
- # basic initialisation
- # only has an effect the first time it's called.
- ######################################################################
-
- proc jedit:init {} {
- global JEDIT_INITIALISED ;# flag - already called?
- if [info exists JEDIT_INITIALISED] {
- return ;# only initialise once
- }
- set JEDIT_INITIALISED 1
-
- global J_PREFS ;# cross-application prefs
- global JEDIT_PREFS ;# editor prefs (all modes)
- global JEDIT_MODEPREFS ;# mode-specific prefs
-
- global JEDIT_WINDOW_COUNT ;# number of toplevel windows
- set JEDIT_WINDOW_COUNT 0
-
- j:jstools_init ;# prefs, libraries, bindings...
-
- global UNDOPTR ;# current index into undo ring
- set UNDOPTR 0
-
- global FILE_MODES ;# filename patterns for modes
- ;# only first two sublist items matter
- set FILE_MODES {
- {*.c code {C source}}
- {*.f code {Fortran source}}
- {*.h code {C header files}}
- {*.jdoc jdoc {document for jdoc app.}}
- {*.jrt richtext {rich-text with fonts and other tags}}
- {*.p code {Pascal source}}
- {*.sh code {Bourne shell script}}
- {*.shar code {Bourne shell archive}}
- {*.tcl tcl {Tcl scripts}}
- {*.tk tcl {Tk/Tcl scripts}}
- {*.exp tcl {Expect scripts}}
- {*/.letter mail {Mail from tin}}
- {.letter mail {Mail from tin}}
- {*/.[a-zA-Z]* code {~/.login, etc.}}
- {.[a-zA-Z]* code {.login, etc.}}
- {*/draft*/[0-9]* mh {MH, exmh, xmh, etc.}}
- {*/tmp/snd.[0-9]* mail {elm}}
- {*/tmp/R*[0-9] mail {UCB Mail}}
- {*.note note {short multi-font note}}
- }
-
- global LINE_MODES ;# first-line patterns for modes
- ;# only first two sublist items matter
- set LINE_MODES {
- {%!* code {PostScript file}}
- {{#!*/wish*} tcl {Tk/Tcl scripts}}
- {{#!*/tclsh*} tcl {Tcl scripts}}
- {{#!*/expect*} tcl {Expect or Expectk scripts}}
- {#!* code {executable script}}
- }
-
- global WORD_END
- set WORD_END {
- ampersand
- apostrophe
- asterisk
- braceright
- bracketright
- colon
- comma
- exclam
- minus
- parenright
- period
- question
- quotedbl
- quoteright
- semicolon
- slash
- underscore
- }
-
- global CUTBUFFER
- set CUTBUFFER {}
-
- global ABBREV ;# last abbrev expanded
- set ABBREV {}
- global ABBREV_POS ;# start of last abbrev
- set ABBREV_POS {}
- global MATCH ;# last match found
- set MATCH {}
- global MATCH_POS ;# position of last match found
- set MATCH_POS {}
- global ABBREV_LIST ;# list of abbrevs read from file
- set ABBREV_LIST {} ;# (not yet used)
- global ABBREVS ;# text-indexed array of expansions
- }
-
- ######################################################################
- # edit a file
- ######################################################################
-
- proc jedit:jedit { args } {
- global JEDIT_PREFS
- global JEDIT_MODEPREFS ;# mode-specific prefs
- global JEDIT_WINDOW_COUNT ;# number of toplevel windows
-
- j:parse_args {
- {window unspecified}
- {mode default}
- {file {}}
- }
-
- jedit:init ;# ignored second etc. time it's called
-
- if {"x$mode" == "xdefault"} { ;# if caller hasn't specified mode
- if {"x$file" != "x"} { ;# and we have a filename
- set mode [jedit:guess_mode $file] ;# guess the mode
- } else { ;# if no filename
- set mode plain ;# empty window in plain mode
- }
- }
-
- # pick a window name if the user hasn't supplied one
- if { "x$window" == "xunspecified" } {
- set window [jedit:new_window_name]
- }
-
- if { ! [winfo exists $window] } {
- toplevel $window
- }
-
- incr JEDIT_WINDOW_COUNT ;# keep count of each window opened
-
- set text [jedit:top_to_text $window]
-
- if {"x$file" != "x"} {
- jedit:set_filename $window $file
- }
- jedit:set_mode $window $mode
-
- jedit:userinit $window $mode $file
- jedit:mkwindow $window
- jedit:apply_mode $window
- jedit:apply_prefs $window
-
- jedit:mkbindings $text $text
- if {[info procs jedit:userhook] == "jedit:userhook"} {
- jedit:userhook $window
- }
- if {"x$file" != "x"} {
- tkwait visibility $text ;# bug workaround for unpatched tk3.6
- jedit:read $file $text
- }
-
- return $window ;# for caller to manipulate
- }
-
- ######################################################################
- # get an unused name for a window
- ######################################################################
-
- proc jedit:new_window_name {} {
- set i 0
- while {[winfo exists .jedit$i]} {
- incr i
- }
- return .jedit$i
- }
-
- ######################################################################
- # user customisation
- ######################################################################
-
- proc jedit:userinit {window mode file} {
- j:debug "jedit:userinit $window $mode $file"
- global J_PREFS ;# cross-application prefs
- global JEDIT_MODEPREFS ;# mode-specific prefs
- global JEDIT_PREFS ;# editor prefs (all modes)
-
- # read in user's editor preferences
- #
- j:read_prefs -array JEDIT_PREFS \
- -file jedit-defaults {
- {textbg white}
- {textfg black}
- {textsb black}
- {textsf white}
- {textiw 2}
- {textbw 2}
- {textsbw 2}
- {undolevels 2}
- }
- jedit:read_mode_prefs $mode
- jedit:cmd:read_abbrevs
-
- # read in user's .tk/jeditrc.tcl
- j:source_config jeditrc.tcl
- }
-
- ######################################################################
- # apply editor and mode preferences (initially or after they change)
- ######################################################################
-
- proc jedit:apply_all_prefs { window } {
- global JEDIT_MODEPREFS ;# mode-specific prefs
- jedit:apply_prefs $window
- jedit:apply_mode $window
- }
-
- ######################################################################
- # apply editor preferences (initially or after they change)
- ######################################################################
-
- proc jedit:apply_prefs { window } {
- global J_PREFS ;# cross-application prefs
- global JEDIT_MODEPREFS ;# mode-specific prefs
- global JEDIT_PREFS ;# editor prefs (all modes)
- global NAME
- global HOME
- global tk_strictMotif
-
- set text [jedit:top_to_text $window]
- set menubar [jedit:top_to_menubar $window]
-
- # set user's text bindings:
-
- j:tb:init Text
- j:eb:init Entry
-
- if {$J_PREFS(tk_strictMotif)} {
- set tk_strictMotif 1
- } else {
- set tk_strictMotif 0
- }
-
- # following are handled by jedit:apply_mode
- # jedit:configure_text $text
- # jedit:mkmenus $menubar $text
- # jedit:mkbuttonbar $buttonbar $text
- }
-
- ######################################################################
- # abbrev - set an abbreviation (used by .tk/abbrevs.tcl
- ######################################################################
-
- proc abbrev {{abbrev} {expansion}} {
- global ABBREVS
-
- set ABBREVS($abbrev) $expansion
- }
-
- ######################################################################
- # regsub in selection in t
- # if the original text ends with a newline, it is removed and
- # replaced at the end.
- ### SHOULD BE MORE GENERAL (eg entire file)
- ######################################################################
-
- proc jedit:text_regsub { t regex subst } {
- if { ! [j:text:has_selection $t]} {
- j:alert -text "No selection made in text."
- return 1
- }
-
- jedit:cmd:save_checkpoint $t ;# save undo information
-
- set finalcr 0
-
- set text [selection get]
- if [regexp -- "\n\$" $text] {
- set text [string trimright $text "\n"]
- set finalcr 1
- }
-
- regsub -all -- $regex $text $subst result
-
- if $finalcr {
- append result "\n"
- }
-
- j:text:replace $t sel.first sel.last $result
- }
-
- ######################################################################
- # pipe selection through command (and replace)
- # if original text has a newline and new text doesn't, a newline
- # is appended. this is a workaround for some filters that drop the
- # newline. not perfect, but should be adequate.
- ######################################################################
-
- proc jedit:pipe { t command } {
- if { ! [j:text:has_selection $t]} {
- j:alert -text "No selection made in text."
- return 1
- }
-
- jedit:cmd:save_checkpoint $t ;# save undo information
-
- set finalcr 0
-
- set text [selection get]
- if [regexp -- "\n\$" $text] {
- set finalcr 1
- }
-
- if { ! $finalcr } { ;# doesn't already have newline
- append text "\n"
- }
-
- if [catch { eval exec $command << [list $text] } result] {
- j:alert -text "Error from $command: $result"
- return 1
- }
-
- if {$finalcr && ( ! [regexp -- "\n\$" $result] )} {
- append result "\n"
- }
-
- j:text:replace $t sel.first sel.last $result
-
- return 0
- }
-
- ######################################################################
- # return string with first char capitalised
- ######################################################################
-
- proc jedit:capitalise {string} {
- set cap [format {%s%s} \
- [string toupper [string range $string 0 0]] \
- [string range $string 1 end]]
- return $cap
- }
-
- ######################################################################
- # return string with first char lowercased
- ######################################################################
-
- proc jedit:uncapitalise {string} {
- set lc [format {%s%s} \
- [string tolower [string range $string 0 0]] \
- [string range $string 1 end]]
- return $lc
- }
-
- ######################################################################
- # go to a particular line
- ######################################################################
-
- proc jedit:go_to_line { t {lineno 0} } {
- set result [catch {
- j:tb:move $t $lineno.0
- }]
- if $result then {j:alert -text "`$lineno' is not a valid line number."}
- }
-
- ######################################################################
- # set the filename corresponding to a window. the window can be
- # specified either as a text widget, or as that text widget's
- # corresponding toplevel window.
- ######################################################################
-
- proc jedit:set_filename { w filename } {
- global JEDIT_FILES
-
- if { [winfo class $w] == "Text" } {
- set window [jedit:text_to_top $w]
- # set text $w
- } else {
- set window $w
- # set text [jedit:top_to_text $w]
- }
-
- set JEDIT_FILES($window) $filename
- }
-
- ######################################################################
- # return the filename corresponding to a window. the window can be
- # specified either as a text widget, or as that text widget's
- # corresponding toplevel window. if no filename has been set for that
- # window, returns {}.
- ######################################################################
-
- proc jedit:get_filename { w } {
- global JEDIT_FILES
-
- if { [winfo class $w] == "Text" } {
- set window [jedit:text_to_top $w]
- # set text $w
- } else {
- set window $w
- # set text [jedit:top_to_text $w]
- }
-
- if [info exists JEDIT_FILES($window)] {
- return $JEDIT_FILES($window)
- } else {
- return {}
- }
- }
-